package com.watermark.util;

import lombok.extern.slf4j.Slf4j;
import net.sourceforge.tess4j.Tesseract;
import net.sourceforge.tess4j.TesseractException;
import org.bytedeco.javacpp.Loader;
import org.bytedeco.opencv.opencv_java;
import org.opencv.core.*;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
import org.springframework.web.multipart.MultipartFile;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import javax.imageio.ImageIO;

import java.util.ArrayList;
import java.util.List;

@Slf4j
public class ImageUtils {
    private static final Tesseract tesseract = new Tesseract();
    
    static {
        try {
            // Load OpenCV native library using JavaCPP
            Loader.load(opencv_java.class);
        } catch (Exception e) {
            throw new RuntimeException("Failed to load OpenCV native library", e);
        }
        
        // 初始化Tesseract
        try {
            tesseract.setDatapath("/usr/local/share/tessdata");  // Tesseract数据目录
            tesseract.setLanguage("eng");  // 设置识别语言为英语
        } catch (Exception e) {
            log.error("Failed to initialize Tesseract: ", e);
        }
    }

    public static Mat loadImage(MultipartFile file) throws IOException {
        Path tempFile = Files.createTempFile("temp", file.getOriginalFilename());
        file.transferTo(tempFile.toFile());
        Mat image = Imgcodecs.imread(tempFile.toString());
        Files.delete(tempFile);
        return image;
    }

    public static void saveImage(Mat image, String outputPath) {
        Imgcodecs.imwrite(outputPath, image);
    }

    public static Mat resizeImage(Mat image, int width, int height) {
        Mat resized = new Mat();
        Size size = new Size(width, height);
        Imgproc.resize(image, resized, size, 0, 0, Imgproc.INTER_AREA);
        return resized;
    }

    public static Mat preprocessImage(Mat image) {
        Mat processed = new Mat();
        
        // 保持原始颜色通道
        image.copyTo(processed);
        
        // 转换为float32以进行更精确的计算
        processed.convertTo(processed, CvType.CV_32F, 1.0/255.0);
        
        return processed;
    }

    public static double calculateSimilarity(Mat img1, Mat img2) {
        if (img1.size() != img2.size()) {
            img2 = resizeImage(img2, img1.cols(), img1.rows());
        }
        
        Mat diff = new Mat();
        Core.absdiff(img1, img2, diff);
        Scalar sum = Core.sumElems(diff);
        
        double totalPixels = img1.rows() * img1.cols() * img1.channels();
        double avgDiff = sum.val[0] / totalPixels;
        
        return 1.0 - avgDiff;
    }

    public static Mat createTextWatermark(String text, int width, int height, 
            String fontName, int fontSize, String color, double opacity, int angle, double density) {
        try {
            // 创建具有透明背景的图像
            BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
            Graphics2D g2d = image.createGraphics();
            
            // 设置渲染提示
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
            
            // 设置字体
            Font font = new Font(fontName, Font.BOLD, fontSize);
            g2d.setFont(font);
            
            // 确保不透明度在有效范围内
            opacity = Math.max(0.0, Math.min(1.0, opacity));
            
            // 解析颜色并应用不透明度
            Color watermarkColor = Color.decode(color);
            int alpha = (int)(opacity * 255);
            g2d.setColor(new Color(
                watermarkColor.getRed(),
                watermarkColor.getGreen(),
                watermarkColor.getBlue(),
                alpha
            ));
            
            // 设置合成模式和透明度
            g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, (float)opacity));
            
            // 获取文字尺寸
            FontMetrics fm = g2d.getFontMetrics();
            int textWidth = fm.stringWidth(text);
            int textHeight = fm.getHeight();
            
            // 根据密度参数调整水印文字的间距
            // density值越大，间距越小，水印越密集
            double spacingFactor = 1.0 / (density > 0 ? density : 1.0);
            int spacingX = (int)((textWidth + 50) * spacingFactor); // 水平间距
            int spacingY = (int)((textHeight + 30) * spacingFactor); // 垂直间距
            
            // 计算需要绘制的行数和列数
            int numRows = (height / spacingY) + 2; // +2 确保覆盖边缘
            int numCols = (width / spacingX) + 2;  // +2 确保覆盖边缘
            
            // 计算起始偏移，使水印居中分布
            int startX = -spacingX/2;
            int startY = textHeight - spacingY/2;
            
            // 如果需要旋转，旋转整个画布
            if (angle != 0) {
                g2d.rotate(Math.toRadians(angle), width/2, height/2);
            }
            
            // 绘制水印文字网格
            for (int row = 0; row < numRows; row++) {
                for (int col = 0; col < numCols; col++) {
                    int x = startX + col * spacingX;
                    int y = startY + row * spacingY;
                    g2d.drawString(text, x, y);
                }
            }
            
            g2d.dispose();
            
            // 转换为Mat
            Mat watermarkMat = bufferedImageToMat(image);
            
            // 转换为4通道BGRA格式
            Mat bgra = new Mat();
            if (watermarkMat.channels() == 3) {
                Imgproc.cvtColor(watermarkMat, bgra, Imgproc.COLOR_BGR2BGRA);
            } else {
                watermarkMat.copyTo(bgra);
            }
            
            // 转换为float32
            bgra.convertTo(bgra, CvType.CV_32F, 1.0/255.0);
            
            return bgra;
        } catch (Exception e) {
            log.error("Failed to create text watermark", e);
            throw new RuntimeException("Failed to create text watermark", e);
        }
    }
    
    public static Mat embedWatermark(Mat originalImage, Mat watermark, double strength) {
        // 确保图像尺寸匹配
        if (originalImage.size() != watermark.size()) {
            watermark = resizeImage(watermark, originalImage.cols(), originalImage.rows());
        }
        
        // 转换原始图像为BGRA
        Mat bgra = new Mat();
        if (originalImage.channels() == 3) {
            Imgproc.cvtColor(originalImage, bgra, Imgproc.COLOR_BGR2BGRA);
        } else {
            originalImage.copyTo(bgra);
        }
        
        // 转换为float32
        bgra.convertTo(bgra, CvType.CV_32F, 1.0/255.0);
        
        // 创建输出图像
        Mat result = new Mat();
        
        // 根据alpha通道混合图像
        Core.addWeighted(bgra, 1.0, watermark, strength, 0.0, result);
        
        // 转换回8位无符号整数
        result.convertTo(result, CvType.CV_8UC4, 255.0);
        
        // 转换回BGR格式
        Mat output = new Mat();
        Imgproc.cvtColor(result, output, Imgproc.COLOR_BGRA2BGR);
        
        return output;
    }
    
    private static Mat bufferedImageToMat(BufferedImage image) throws IOException {
        // 将BufferedImage转换为字节数组
        java.io.ByteArrayOutputStream byteArrayOutputStream = new java.io.ByteArrayOutputStream();
        ImageIO.write(image, "png", byteArrayOutputStream);
        byteArrayOutputStream.flush();
        byte[] imageInByte = byteArrayOutputStream.toByteArray();
        byteArrayOutputStream.close();
        
        // 将字节数组转换为Mat，使用IMREAD_UNCHANGED保持原始颜色和alpha通道
        Mat mat = Imgcodecs.imdecode(new MatOfByte(imageInByte), Imgcodecs.IMREAD_UNCHANGED);
        
        // 确保颜色通道顺序正确（BGRA）
        if (mat.channels() == 4) {
            Mat bgra = new Mat();
            Imgproc.cvtColor(mat, bgra, Imgproc.COLOR_RGBA2BGRA);
            return bgra;
        }
        return mat;
    }

    public static void createDirectoryIfNotExists(String dir) throws IOException {
        Path path = Path.of(dir);
        if (!Files.exists(path)) {
            Files.createDirectories(path);
        }
    }

    public static Mat preprocessForOCR(Mat image) {
        // 转换为灰度图像
        Mat gray = new Mat();
        if (image.channels() > 1) {
            Imgproc.cvtColor(image, gray, Imgproc.COLOR_BGR2GRAY);
        } else {
            image.copyTo(gray);
        }
        
        // 应用自适应阈值处理
        Mat binary = new Mat();
        Imgproc.adaptiveThreshold(gray, binary, 255,
            Imgproc.ADAPTIVE_THRESH_GAUSSIAN_C,
            Imgproc.THRESH_BINARY,
            11, 2);
            
        // 降噪
        Mat denoised = new Mat();
        Imgproc.medianBlur(binary, denoised, 3);
        
        // 增强对比度
        Mat enhanced = new Mat();
        Core.normalize(denoised, enhanced, 0, 255, Core.NORM_MINMAX);
        
        return enhanced;
    }

    public static String performOCR(Mat image) {
        try {
            // 预处理图像
            Mat processedImage = preprocessForOCR(image);
            
            // 保存处理后的图像用于调试
            String debugPath = "debug_ocr_processed_" + System.currentTimeMillis() + ".png";
            Imgcodecs.imwrite(debugPath, processedImage);
            
            // 将OpenCV的Mat转换为BufferedImage
            MatOfByte mob = new MatOfByte();
            Imgcodecs.imencode(".png", processedImage, mob);
            byte[] byteArray = mob.toArray();
            BufferedImage bufferedImage = ImageIO.read(new ByteArrayInputStream(byteArray));
            
            // 设置Tesseract参数
            tesseract.setPageSegMode(3); // 假设页面为统一文本
            tesseract.setTessVariable("user_defined_dpi", "300");
            
            // 执行OCR
            String result = tesseract.doOCR(bufferedImage).trim();
            log.info("OCR Result: {}", result);
            return result;
        } catch (Exception e) {
            log.error("Error performing OCR: ", e);
            return "";
        }
    }
} 